/* $RCSFile: GenericDynQueryMultiple.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/GenericDynQueryMultiple.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:32  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Data;
using System.Web.Services.Protocols;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

using CrmSdk;

namespace AddonNice.CRMWrapper
{
		
	/// <summary>
    /// Adds Multiple Query Funtionnalities 

    /// </summary>
	public class GenericDynQueryMultiple<T> where T:DynEntity, new()
    {
        string	_Name   						                =   string.Empty;
        CRMWrapperBase _wrapper						            =   null;
        ResetWrapperHandler ResetWrapper                        =   null;
        
        /// <summary>
        /// Returns all results, if return_bindable was set => result are returned as Bindable list else as list of dicProperties
        /// </summary>
        /// <returns></returns>
        public CRMWrapperBase wrapper 
        {
            get {  return _wrapper;  }
        }

		/// <summary>
		/// Beware, this is the entityname, not the name Property
		/// </summary>
        public string Name 
        {
            get {  return _Name;  }
        }

        bool _isAdmin  =   false;
        public bool isAdmin
        {
            get
            {
                return _isAdmin;
            }
            set
            {
                 _isAdmin  =   value;
            }
        }

        InternalQueryExpression _Query  =   null;
        public InternalQueryExpression Query 
        {
            get {  return _Query;  }
        }

        InternalResponse _Retrieved     =   null;
        public InternalResponse Retrieved
        {
            get {  return _Retrieved;  }
        }

        int _RetrievedCount             =   0;
        public int RetrievedCount
        {
            get {  return _RetrievedCount;  }
        }

        #region paging

        bool _UsePaging  =   false;
        public bool UsePaging
        {
            get
            {
                return _UsePaging;
            }
            set
            {
                 _UsePaging  =   value;
            }
        }


        int _PageSize   =   10;
        public int PageSize
        {
            get
            {
                return _PageSize;
            }
            set
            {
                _PageSize   =   value;
            }
        }

        int _PageNumber =   1; 
        /// <summary>
        /// Start at 1 !
        /// </summary>
        public int PageNumber
        {
            get
            {
                return _PageNumber;
            }
            set
            {
                _PageNumber   =   value;
            }
        }

        string _PagingCookie    =   string.Empty;
        public string PagingCookie
        {
            get
            {
                return _PagingCookie;
            }
            set
            {
                _PagingCookie   =   value;
            }
        }

        bool _MoreRecords  =   false;
        public bool MoreRecords
        {
            get
            {
                return _MoreRecords;
            }
            set
            {
                 _MoreRecords  =   value;
            }
        }
        #endregion paging

        /// <summary>
        /// constructor used for creation
        /// </summary>
        public GenericDynQueryMultiple(CRMWrapperBase w,ResetWrapperHandler fn, string name) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple Constructor with name : {0}",name),CRMQueryTraceSwitch.Sw.Info);
            _Name			=   name;
            _wrapper		=   w;
            ResetWrapper    =   fn;
        }

		/// <summary>
        /// constructor used for creation
        /// </summary>
        public GenericDynQueryMultiple(CRMWrapperBase w,ResetWrapperHandler fn) 
        {
			if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( "[V]GenericDynQueryMultiple Constructor",CRMQueryTraceSwitch.Sw.Info);
            _wrapper		=   w;
            ResetWrapper    =   fn;
        }

        /// <summary>
        /// Retrieving a SortedList Guid,T with current user rights, query must be set before
        /// </summary>
        public SortedList<Guid,T> retrieveSortedList() 
        {
            if (UsePaging)
            {
                _Query.PageInfo                 =   new InternalPagingInfo();
                _Query.PageInfo.PageNumber      =   PageNumber;
                _Query.PageInfo.Count           =   PageSize;
            }

            SortedList<Guid,T> Lst              =   wrapper.Util.QueryAsSortedList<T>(_Query,ResetWrapper,_isAdmin,ref _PagingCookie,ref _MoreRecords);
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveDatatable with query",CRMQueryTraceSwitch.Sw.Info);
            return Lst;
        }


        /// <summary>
        /// Retrieving a SortedList Guid,T with current user rights and a query to allow specific query parameters
        /// </summary>
        public SortedList<Guid,T> retrieveSortedList(InternalQueryExpression qe) 
        {
            _Query                              =   qe;
            if (UsePaging)
            {
                _Query.PageInfo                 =   new InternalPagingInfo();
                _Query.PageInfo.PageNumber      =   PageNumber;
                _Query.PageInfo.Count           =   PageSize;
            }

            SortedList<Guid,T> Lst              =   wrapper.Util.QueryAsSortedList<T>(_Query,ResetWrapper,_isAdmin,ref _PagingCookie,ref _MoreRecords);
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveDatatable with query",CRMQueryTraceSwitch.Sw.Info);
            return Lst;
        }

        /// <summary>
        /// Retrieving Next SortedList<Guid,T> with current user rights and a query to allow specific query parameters
        /// </summary>
        public SortedList<Guid,T> retrieveNextSortedList() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveNextSortedList",CRMQueryTraceSwitch.Sw.Info);
            PrepareQueryForNextPage();            
            SortedList<Guid,T> Lst  =   wrapper.Util.QueryAsSortedList<T>(_Query,ResetWrapper,_isAdmin,ref _PagingCookie,ref _MoreRecords);
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveNextSortedList with query.",CRMQueryTraceSwitch.Sw.Info);
            return Lst;
        }

        /// <summary>
        /// Retrieving a DataTable with current user rights and a query to allow specific query parameters
        /// </summary>
        public GenericCrmTable<T> retrieveDatatable(InternalQueryExpression qe) 
        {
            _Query  =   qe;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveDatatable with query",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,Retrieve(qe),qe);
        }
        
        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public GenericCrmTable<T> retrieveDatatable() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveDatatable ",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,Retrieve(),null);
        }
         
        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public GenericCrmTable<T> retrieveNextDatatable(InternalQueryExpression qe) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveNextDatatable ",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,RetrieveNextPage(),qe);
        }

        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public GenericCrmTable<T> retrieveNextDatatable() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple retrieveNextDatatable ",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,RetrieveNextPage(),null);
        }

        /// <summary>
        /// Retrieve a Bindable list of entities with the EntityID set on constructor and a specific query
        /// current user rights
        /// </summary>
        public GenericBindableList<T>  BindRetrieve(InternalQueryExpression query) 
        {
            _Query  =   query;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple BindRetrieve with query Name: {0}",Name),CRMQueryTraceSwitch.Sw.Info);
            return internalBindRetrieve();
        }

        /// <summary>
        /// Retrieve a Bindable list of entities with the EntityID set on constructor 
        /// current user rights
        /// without query, a default one will be created with all columns
        /// </summary>
        public GenericBindableList<T>  BindRetrieve() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple BindRetrieve Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return internalBindRetrieve();
        }

        /// <summary>
        /// Retrieve a Bindable list of entities with the EntityID set on constructor and a specific query
        /// admin user rights
        /// </summary>
        public GenericBindableList<T>  adminBindRetrieve(InternalQueryExpression query) 
        {
            _Query      =   query;
            _isAdmin    =   true;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple adminBindRetrieve with query",CRMQueryTraceSwitch.Sw.Info);
            return internalBindRetrieve();
        }

        /// <summary>
        /// Retrieve a Bindable list of entities with the EntityID set on constructor 
        /// admin user rights
        /// without query, a default one will be created with all columns
        /// </summary>
        public GenericBindableList<T> adminBindRetrieve() 
        {
            _isAdmin    =   true;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple adminBindRetrieve : building query for Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return internalBindRetrieve();
        }

        public GenericBindableList<T> BindRetrieveNext() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple adminBindRetrieveNext : building query for :: Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return new GenericBindableList<T>(_wrapper, RetrieveNextPage());
        }

        /// <summary>
        /// Internal method which retrieve a Bindable Lst of entities according to parameters query and isAdmin
        /// </summary>
        private GenericBindableList<T> internalBindRetrieve()
        {
            return new GenericBindableList<T>(_wrapper, internalRetrieve());
        }

        /// <summary>
        /// Retrieve a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// Specific query
        /// current user rights
        /// </summary>
        public InternalBusinessEntityCollection Retrieve(InternalQueryExpression query) 
        {
            _Query      =   query;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple Retrieve Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return internalRetrieve();
        }

        /// <summary>
        /// Retrieve a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// a default query will be generated with all columns
        /// current user rights
        /// </summary>
        public InternalBusinessEntityCollection Retrieve() 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple Retrieve Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return internalRetrieve();
        }

        /// <summary>
        /// Retrieve a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// a default query will be generated with all columns
        /// admin user rights
        /// </summary>
        public InternalBusinessEntityCollection adminRetrieve(InternalQueryExpression query) 
        {
            _Query      =   query;
            _isAdmin    =   true;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple adminRetrieve with query",CRMQueryTraceSwitch.Sw.Info);
            return internalRetrieve();
        }

        /// <summary>
        /// Retrieve a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// a default query will be generated with all columns
        /// admin user rights
        /// </summary>
        public InternalBusinessEntityCollection adminRetrieve() 
        {
            _isAdmin    =   true;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple adminRetrieve Name: {0}", Name),CRMQueryTraceSwitch.Sw.Info);
            return internalRetrieve();
        }

        /// <summary>
        /// Internal usage for methods with BusnessEntityCollection return
        /// </summary>
        private InternalBusinessEntityCollection internalRetrieve() 
        {
            // Set the properties of the request object.
            if ( _Query  == null ) 
            {
                if (string.IsNullOrEmpty(_Name)) 
                {
                    string msg                      =   string.Format("[E]GenericDynQueryMultiple internalRetrieve Name is empty ");
                    if ( CRMQueryTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( msg,CRMQueryTraceSwitch.Sw.Info);
                    throw new CRMWrapperException(msg);
                }                
                _Query                              =   new InternalQueryExpression();
                // Set the properties of the default QueryExpression.
                _Query.EntityName                   =   Name;
                _Query.ColumnSet                    =   new InternalAllColumns();
            }

            if (UsePaging)
            {
                _Query.PageInfo                     =   new InternalPagingInfo();
                _Query.PageInfo.PageNumber          =   PageNumber;
                _Query.PageInfo.Count               =   PageSize;
            }
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple internalRetrieve EntityName: {0}, ColumnSet: {1}.", 
                    _Query.EntityName,_Query.ColumnSet),CRMQueryTraceSwitch.Sw.Info);
            if (CRMQueryTraceSwitch.Sw.TraceVerbose && (_Query.ColumnSet is InternalColumnSet) )
            {
                for (int i = 0; i < ((InternalColumnSet)_Query.ColumnSet).Attributes.Length; i++)
                    if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple internalRetrieve i: {0}, _Query.InternalColumnSet.Attributes: [{1}]", i, 
                            ((InternalColumnSet)_Query.ColumnSet).Attributes[i]),CRMQueryTraceSwitch.Sw.Info);
            }

            InternalRetrieveMultipleRequest retrieve=   wrapper.MakeRetrieveMultipleRequest(Query,true);
            // Execute the request.
            try 
            {
                if (isAdmin)
                    _Retrieved                      =   wrapper.adminExecute(retrieve);
                else
                    _Retrieved                      =   wrapper.userExecute(retrieve);
                _RetrievedCount                     =   0;
                InternalBusinessEntityCollection beCol   =   wrapper.Util.ExtractBusinessCollection(Retrieved,ref _RetrievedCount);
                wrapper.Util.ExtractPagingInfo(beCol,ref _PagingCookie,ref _MoreRecords);
                return beCol;
            } 
            catch (SoapException sex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple internalRetrieve soap ex: {0}", sex.Detail.InnerText),CRMQueryTraceSwitch.Sw.Info);
                _MoreRecords                        =   false;
                throw;
            }
            catch (Exception ex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple internalRetrieve ex: {0}",ex),CRMQueryTraceSwitch.Sw.Info);
                _MoreRecords                        =   false;
                throw;
            }
        }


        /// <summary>
        /// When paging is used or more records could be retrieved
        /// </summary>
        public InternalBusinessEntityCollection RetrieveNextPage() 
        {
            PrepareQueryForNextPage();            
            InternalRetrieveMultipleRequest retrieve    =   wrapper.MakeRetrieveMultipleRequest(Query,true);
            // Execute the request.
            try 
            {
                if (isAdmin)
                    _Retrieved                          =   wrapper.adminExecute(retrieve);
                else
                    _Retrieved                          =   wrapper.userExecute(retrieve);
                _RetrievedCount                         =   0;
                InternalBusinessEntityCollection beCol  =   wrapper.Util.ExtractBusinessCollection(Retrieved,ref _RetrievedCount);
                wrapper.Util.ExtractPagingInfo(beCol,ref _PagingCookie,ref _MoreRecords);
                return beCol;
            } 
            catch (SoapException sex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple RetrieveNextPage soap ex: {0}", sex.Detail.InnerText),CRMQueryTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple RetrieveNextPage ex: {0}", ex),CRMQueryTraceSwitch.Sw.Info);
                throw;
            }
        }

        #region Rollup

        /// <summary>
        /// Rollup a DataTable with current user rights and a query to allow specific query parameters
        /// </summary>
        public DataTable RollupDatatable(string rollupEntityName,Guid rollupEntityId,InternalQueryExpression qe) 
        {
            _Query  =   qe;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple RollupDatatable with query BEG.",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,Rollup(rollupEntityName,rollupEntityId,qe),qe);
        }
        
        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public DataTable RollupDatatable(string rollupEntityName,Guid rollupEntityId) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple RollupDatatable BEG all.",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,Rollup(rollupEntityName,rollupEntityId),null);
        }
         
        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public DataTable RollupNextDatatable(string rollupEntityName,Guid rollupEntityId,InternalQueryExpression qe) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple RollupNextDatatable BEG with query.",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,RollupNextPage(rollupEntityName,rollupEntityId),qe);
        }

        /// <summary>
        /// Retrieving a DataTable without query, a default one will be created with all columns
        /// </summary>
        public DataTable RollupNextDatatable(string rollupEntityName,Guid rollupEntityId) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine("[V]GenericDynQueryMultiple RollupNextDatatable BEG All.",CRMQueryTraceSwitch.Sw.Info);
            return new GenericCrmTable<T>(wrapper,ResetWrapper,RollupNextPage(rollupEntityName,rollupEntityId),null);
        }
        
        /// <summary>
        /// Rollup a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// Specific query
        /// current user rights
        /// </summary>
        public InternalBusinessEntityCollection Rollup(string rollupEntityName,Guid rollupEntityId,InternalQueryExpression query) 
        {
            _Query      =   query;
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple Rollup Name: {0}, rollupEntityName: {1}, rollupEntityId: {2}", 
                    Name,rollupEntityName,rollupEntityId),CRMQueryTraceSwitch.Sw.Info);
            return internalRollup(rollupEntityName,rollupEntityId);
        }

        /// <summary>
        /// Rollup a BusinessEntityCollection dynamically with the EntityID set on constructor
        /// a default query will be generated with all columns
        /// current user rights
        /// </summary>
        public InternalBusinessEntityCollection Rollup(string rollupEntityName,Guid rollupEntityId) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple Rollup Name: {0}, rollupEntityName: {1}, rollupEntityId: {2}", 
                    Name,rollupEntityName,rollupEntityId),CRMQueryTraceSwitch.Sw.Info);
            return internalRollup(rollupEntityName,rollupEntityId);
        }

        /// <summary>
        /// Internal usage for methods with BusnessEntityCollection return
        /// </summary>
        private InternalBusinessEntityCollection internalRollup(string rollupEntityName,Guid rollupEntityId) 
        {
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple internalRollup Name: {0}, rollupEntityName: {1}, rollupEntityId: {2}", 
                    Name,rollupEntityName,rollupEntityId),CRMQueryTraceSwitch.Sw.Info);
            // Set the properties of the request object.
            if ( _Query  == null ) 
            {
                if (string.IsNullOrEmpty(_Name)) 
                {
                    string msg  =   String.Format("[E]GenericDynQueryMultiple internalRollup Name is empty ");
                    if ( CRMQueryTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( msg,CRMQueryTraceSwitch.Sw.Info);
                    throw new CRMWrapperException(msg);
                }                
                _Query                                  =   new InternalQueryExpression();
                // Set the properties of the default QueryExpression.
                _Query.EntityName                       =   Name;
                _Query.ColumnSet                        =   new InternalAllColumns();
            }

            if (UsePaging)
            {
                _Query.PageInfo                         =   new InternalPagingInfo();
                _Query.PageInfo.PageNumber              =   PageNumber;
                _Query.PageInfo.Count                   =   PageSize;
            }
            if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple internalRollup EntityName: {0}, ColumnSet: {1}.", 
                    _Query.EntityName,_Query.ColumnSet),CRMQueryTraceSwitch.Sw.Info);
            if (CRMQueryTraceSwitch.Sw.TraceVerbose && (_Query.ColumnSet is InternalColumnSet) )
            {
                for (int i = 0; i < ((InternalColumnSet)_Query.ColumnSet).Attributes.Length; i++)
                    if ( CRMQueryTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]GenericDynQueryMultiple internalRollup i: {0}, _Query.InternalColumnSet.Attributes: [{1}]", i, 
                            ((InternalColumnSet)_Query.ColumnSet).Attributes[i]),CRMQueryTraceSwitch.Sw.Info);
            }

            // Execute the request.
            try 
            {
                if (isAdmin)
                    _Retrieved                          =   wrapper.adminRollup(rollupEntityName,rollupEntityId,_Query,true);
                else
                    _Retrieved                          =   wrapper.userRollup(rollupEntityName,rollupEntityId,_Query,true);
                _RetrievedCount                         =   0;
                InternalBusinessEntityCollection beCol  =   wrapper.Util.ExtractBusinessCollection(Retrieved,ref _RetrievedCount);
                wrapper.Util.ExtractPagingInfo(beCol,ref _PagingCookie,ref _MoreRecords);
                return beCol;
            } 
            catch (SoapException sex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple internalRollup soap ex: {0}", sex.Detail.InnerText),CRMQueryTraceSwitch.Sw.Info);
                _MoreRecords                            =   false;
                throw;
            }
            catch (Exception ex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple internalRollup ex: {0}",ex),CRMQueryTraceSwitch.Sw.Info);
                _MoreRecords                            =   false;
                throw;
            }
        }
        
        /// <summary>
        /// When paging is used or more records could be retrieved
        /// </summary>
        public InternalBusinessEntityCollection RollupNextPage(string rollupEntityName,Guid rollupEntityId) 
        {
            PrepareQueryForNextPage();            
            // Execute the request.
            try 
            {
                if (isAdmin)
                    _Retrieved                          =   wrapper.adminRollup(Name,rollupEntityId,_Query,true);
                else
                    _Retrieved                          =   wrapper.userRollup(Name,rollupEntityId,_Query,true);
                _RetrievedCount                         =   0;
                InternalBusinessEntityCollection beCol  =   wrapper.Util.ExtractBusinessCollection(Retrieved,ref _RetrievedCount);
                wrapper.Util.ExtractPagingInfo(beCol,ref _PagingCookie,ref _MoreRecords);
                return beCol;
            } 
            catch (SoapException sex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple RollupNextPage soap ex: {0}", sex.Detail.InnerText),CRMQueryTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex) 
            {
                if ( CRMQueryTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]GenericDynQueryMultiple RollupNextPage ex: {0}", ex),CRMQueryTraceSwitch.Sw.Info);
                throw;
            }
        }
        #endregion Rollup
        
        
        /// <summary>
        /// Prepare the previously used query for next page when paging is necessary
        /// </summary>
        void PrepareQueryForNextPage()
        {
            // Set the properties of the request object.
            if ( _Query  == null ) 
            {
                if (string.IsNullOrEmpty(_Name)) 
                {
                    string msg  =   "[E]GenericDynQueryMultiple RetrieveNextPage {0} Name is empty";
                    if ( CRMQueryTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( msg,CRMQueryTraceSwitch.Sw.Info);
                    throw new CRMWrapperException(msg);
                }                
                _Query                      =   new InternalQueryExpression();
                // Set the properties of the default QueryExpression.
                _Query.EntityName           =   Name;
                _Query.ColumnSet            =   new InternalAllColumns();
            }

            _Query.PageInfo                 =   new InternalPagingInfo();
            _Query.PageInfo.PageNumber      =   ++PageNumber;
            _Query.PageInfo.Count           =   PageSize;
            _Query.PageInfo.PagingCookie    =   PagingCookie;
        }
    }
}
